package com.andnnl.ratelimit;

import com.andnnl.future.ThreadUtil;
import com.google.common.util.concurrent.RateLimiter;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * 做接口访问限制，访问一次获取一批数据，如果每个用户访问有数据，每秒最多访问10次，如果没数据，直接返回空，1秒最多访问1次，接口支持多用户同时访问的，每个用户需要自己的RateLimiter
 * Created by chenss on 2024/3/18.
 */
public class SdkAccessLimitTest2 {

    private static final Map<String, RateLimiter> rateLimitersWithData = new ConcurrentHashMap<>();//有数据的用户限制，每秒10次
    private static final Map<String, RateLimiter> rateLimitersWithoutData = new ConcurrentHashMap<>();//没有数据的用户限制，每秒2次
    private static final Map<String, Boolean> lastHasDataMap = new HashMap<>();//记录上次的
    public static final int PERMITS_WITH_DATA = 5;
    public static final int PERMITS_WITHOUT_DATA = 2;

    public static void main(String[] args) {
        ExecutorService pool = Executors.newFixedThreadPool(4);
        for (int i = 0; i < 1; i++) {
            pool.submit(()->test1());
        }
    }

    private static void test1() {
        // 模拟用户访问接口
        for (int i = 0; i < 20; i++) {
            String userId = "user" + i % 2;
            boolean lastHasData = lastHasDataMap.getOrDefault(userId, false); // 模拟数据是否存在

            RateLimiter limiter;
            if (lastHasData) {
                limiter = rateLimitersWithData.computeIfAbsent(userId, k -> RateLimiter.create(PERMITS_WITH_DATA));
            } else {
                limiter = rateLimitersWithoutData.computeIfAbsent(userId, k -> RateLimiter.create(PERMITS_WITHOUT_DATA));
            }

            if (!limiter.tryAcquire()) {
                System.out.println(System.currentTimeMillis() + " " + userId + " failed to access the API \thasData:" + lastHasData);
                continue;//访问失败的，直接返回
            }
            System.out.println(System.currentTimeMillis() + " " + userId + " accessed the API \t\thasData:" + lastHasData);
            boolean hasData = i % 2 == 0;
            lastHasDataMap.put(userId, hasData);//记录上次有没有数据
            ThreadUtil.sleep(200);
        }
    }
}
